/***** Lobxxx Translate Finished ******/
/*
 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.awt.event;

import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.awt.IllegalComponentStateException;
import java.awt.MouseInfo;
import sun.awt.SunToolkit;

/**
 * An event which indicates that a mouse action occurred in a component.
 * A mouse action is considered to occur in a particular component if and only
 * if the mouse cursor is over the unobscured part of the component's bounds
 * when the action happens.
 * For lightweight components, such as Swing's components, mouse events
 * are only dispatched to the component if the mouse event type has been
 * enabled on the component. A mouse event type is enabled by adding the
 * appropriate mouse-based {@code EventListener} to the component
 * ({@link MouseListener} or {@link MouseMotionListener}), or by invoking
 * {@link Component#enableEvents(long)} with the appropriate mask parameter
 * ({@code AWTEvent.MOUSE_EVENT_MASK} or {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}).
 * If the mouse event type has not been enabled on the component, the
 * corresponding mouse events are dispatched to the first ancestor that
 * has enabled the mouse event type.
 *<p>
 * For example, if a {@code MouseListener} has been added to a component, or
 * {@code enableEvents(AWTEvent.MOUSE_EVENT_MASK)} has been invoked, then all
 * the events defined by {@code MouseListener} are dispatched to the component.
 * On the other hand, if a {@code MouseMotionListener} has not been added and
 * {@code enableEvents} has not been invoked with
 * {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}, then mouse motion events are not
 * dispatched to the component. Instead the mouse motion events are
 * dispatched to the first ancestors that has enabled mouse motion
 * events.
 * <P>
 * This low-level event is generated by a component object for:
 * <ul>
 * <li>Mouse Events
 *     <ul>
 *     <li>a mouse button is pressed
 *     <li>a mouse button is released
 *     <li>a mouse button is clicked (pressed and released)
 *     <li>the mouse cursor enters the unobscured part of component's geometry
 *     <li>the mouse cursor exits the unobscured part of component's geometry
 *     </ul>
 * <li> Mouse Motion Events
 *     <ul>
 *     <li>the mouse is moved
 *     <li>the mouse is dragged
 *     </ul>
 * </ul>
 * <P>
 * A <code>MouseEvent</code> object is passed to every
 * <code>MouseListener</code>
 * or <code>MouseAdapter</code> object which is registered to receive
 * the "interesting" mouse events using the component's
 * <code>addMouseListener</code> method.
 * (<code>MouseAdapter</code> objects implement the
 * <code>MouseListener</code> interface.) Each such listener object
 * gets a <code>MouseEvent</code> containing the mouse event.
 * <P>
 * A <code>MouseEvent</code> object is also passed to every
 * <code>MouseMotionListener</code> or
 * <code>MouseMotionAdapter</code> object which is registered to receive
 * mouse motion events using the component's
 * <code>addMouseMotionListener</code>
 * method. (<code>MouseMotionAdapter</code> objects implement the
 * <code>MouseMotionListener</code> interface.) Each such listener object
 * gets a <code>MouseEvent</code> containing the mouse motion event.
 * <P>
 * When a mouse button is clicked, events are generated and sent to the
 * registered <code>MouseListener</code>s.
 * The state of modal keys can be retrieved using {@link InputEvent#getModifiers}
 * and {@link InputEvent#getModifiersEx}.
 * The button mask returned by {@link InputEvent#getModifiers} reflects
 * only the button that changed state, not the current state of all buttons.
 * (Note: Due to overlap in the values of ALT_MASK/BUTTON2_MASK and
 * META_MASK/BUTTON3_MASK, this is not always true for mouse events involving
 * modifier keys).
 * To get the state of all buttons and modifier keys, use
 * {@link InputEvent#getModifiersEx}.
 * The button which has changed state is returned by {@link MouseEvent#getButton}
 * <P>
 * For example, if the first mouse button is pressed, events are sent in the
 * following order:
 * <PRE>
 *    <b   >id           </b   >   <b   >modifiers   </b   > <b   >button </b   >
 *    <code>MOUSE_PRESSED</code>:  <code>BUTTON1_MASK</code> <code>BUTTON1</code>
 *    <code>MOUSE_RELEASED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
 *    <code>MOUSE_CLICKED</code>:  <code>BUTTON1_MASK</code> <code>BUTTON1</code>
 * </PRE>
 * When multiple mouse buttons are pressed, each press, release, and click
 * results in a separate event.
 * <P>
 * For example, if the user presses <b>button 1</b> followed by
 * <b>button 2</b>, and then releases them in the same order,
 * the following sequence of events is generated:
 * <PRE>
 *    <b   >id           </b   >   <b   >modifiers   </b   > <b   >button </b   >
 *    <code>MOUSE_PRESSED</code>:  <code>BUTTON1_MASK</code> <code>BUTTON1</code>
 *    <code>MOUSE_PRESSED</code>:  <code>BUTTON2_MASK</code> <code>BUTTON2</code>
 *    <code>MOUSE_RELEASED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
 *    <code>MOUSE_CLICKED</code>:  <code>BUTTON1_MASK</code> <code>BUTTON1</code>
 *    <code>MOUSE_RELEASED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
 *    <code>MOUSE_CLICKED</code>:  <code>BUTTON2_MASK</code> <code>BUTTON2</code>
 * </PRE>
 * If <b>button 2</b> is released first, the
 * <code>MOUSE_RELEASED</code>/<code>MOUSE_CLICKED</code> pair
 * for <code>BUTTON2_MASK</code> arrives first,
 * followed by the pair for <code>BUTTON1_MASK</code>.
 * <p>
 * Some extra mouse buttons are added to extend the standard set of buttons
 * represented by the following constants:{@code BUTTON1}, {@code BUTTON2}, and {@code BUTTON3}.
 * Extra buttons have no assigned {@code BUTTONx}
 * constants as well as their button masks have no assigned {@code BUTTONx_DOWN_MASK}
 * constants. Nevertheless, ordinal numbers starting from 4 may be
 * used as button numbers (button ids). Values obtained by the
 * {@link InputEvent#getMaskForButton(int) getMaskForButton(button)} method may be used
 * as button masks.
 * <p>
 * {@code MOUSE_DRAGGED} events are delivered to the {@code Component}
 * in which the mouse button was pressed until the mouse button is released
 * (regardless of whether the mouse position is within the bounds of the
 * {@code Component}).  Due to platform-dependent Drag&amp;Drop implementations,
 * {@code MOUSE_DRAGGED} events may not be delivered during a native
 * Drag&amp;Drop operation.
 *
 * In a multi-screen environment mouse drag events are delivered to the
 * <code>Component</code> even if the mouse position is outside the bounds of the
 * <code>GraphicsConfiguration</code> associated with that
 * <code>Component</code>. However, the reported position for mouse drag events
 * in this case may differ from the actual mouse position:
 * <ul>
 * <li>In a multi-screen environment without a virtual device:
 * <br>
 * The reported coordinates for mouse drag events are clipped to fit within the
 * bounds of the <code>GraphicsConfiguration</code> associated with
 * the <code>Component</code>.
 * <li>In a multi-screen environment with a virtual device:
 * <br>
 * The reported coordinates for mouse drag events are clipped to fit within the
 * bounds of the virtual device associated with the <code>Component</code>.
 * </ul>
 * <p>
 * An unspecified behavior will be caused if the {@code id} parameter
 * of any particular {@code MouseEvent} instance is not
 * in the range from {@code MOUSE_FIRST} to {@code MOUSE_LAST}-1
 * ({@code MOUSE_WHEEL} is not acceptable).
 *
 * <p>
 *  指示在组件中发生鼠标操作的事件。当且仅当当动作发生时鼠标光标位于组件边界的未遮挡部分上时,认为鼠标动作发生在特定组件中。
 * 对于轻量级组件(例如Swing的组件),只有在组件上启用了鼠标事件类型时,才会将鼠标事件分派给组件。
 * 通过向组件({@link MouseListener}或{@link MouseMotionListener})添加适当的基于鼠标的{@code EventListener}或通过调用{@link Component#enableEvents(long)}
 * 来启用鼠标事件类型适当的掩码参数({@code AWTEvent.MOUSE_EVENT_MASK}或{@code AWTEvent.MOUSE_MOTION_EVENT_MASK})。
 * 对于轻量级组件(例如Swing的组件),只有在组件上启用了鼠标事件类型时,才会将鼠标事件分派给组件。如果组件上尚未启用鼠标事件类型,则相应的鼠标事件将分派到启用鼠标事件类型的第一个祖先。
 * p>
 * 例如,如果{@code MouseListener}已添加到组件中,或{@code enableEvents(AWTEvent.MOUSE_EVENT_MASK)}已被调用,则{@code MouseListener}
 * 定义的所有事件都将被分派到组件。
 * 另一方面,如果尚未添加{@code MouseMotionListener}并且尚未使用{@code AWTEvent.MOUSE_MOTION_EVENT_MASK}调用{@code enableEvents}
 * ,则不会将鼠标移动事件分派给组件。
 * 相反,鼠标运动事件被分派到已经启用鼠标运动事件的第一祖先。
 * <P>
 *  此低级事件由组件对象生成,用于：
 * <ul>
 *  <li>鼠标事件
 * <ul>
 *  <li>鼠标按钮被释放<li>鼠标按钮被点击(按下并释放)<li>鼠标光标进入部件几何的未隐藏部分<li>鼠标光标退出组件几何的未遮挡部分
 * </ul>
 *  <li>鼠标移动事件
 * <ul>
 *  <li>鼠标被移动<li>鼠标被拖动
 * </ul>
 * </ul>
 * <P>
 *  一个<code> MouseEvent </code>对象被传递到每个<code> MouseListener </code>或<code> MouseAdapter </code>对象,它注册接收"
 * 有趣的"鼠标事件使用组件的<code> addMouseListener </code>方法。
 *  (<code> MouseAdapter </code>对象实现<code> MouseListener </code>接口。
 * )每个这样的监听器对象获取一个包含鼠标事件的<code> MouseEvent </code>。
 * <P>
 * 一个<code> MouseEvent </code>对象也被传递给每一个<code> MouseMotionListener </code>或<code> MouseMotionAdapter </code>
 * 对象,它被注册为接收鼠标运动事件,使用组件的<code> addMouseMotionListener <代码>方法。
 *  (<code> MouseMotionAdapter </code>对象实现<code> MouseMotionListener </code>接口。
 * )每个这样的监听器对象获取一个包含鼠标运动事件的<code> MouseEvent </code>。
 * <P>
 *  当点击鼠标按钮时,生成事件并发送到注册的<code> MouseListener </code>。
 * 模态键的状态可以使用{@link InputEvent#getModifiers}和{@link InputEvent#getModifiersEx}来检索。
 *  {@link InputEvent#getModifiers}返回的按钮掩码仅反映更改状态的按钮,而不是所有按钮的当前状态。
 *  (注意：由于ALT_MASK / BUTTON2_MASK和META_MASK / BUTTON3_MASK的值重叠,这对于涉及修改键的鼠标事件不总是正确的。
 * 要获取所有按钮和修饰键的状态,请使用{@link InputEvent#getModifiersEx}。已更改状态的按钮由{@link MouseEvent#getButton}返回。
 * <P>
 *  例如,如果按下第一个鼠标按钮,事件按以下顺序发送：
 * <PRE>
 * <b> </b> <b> <b> </b> <b> </b> <b>代码> MOUSE_RELEASED </code>：<code> BUTTON1_MASK </code> <code> BUTTO
 * N1_MASK </code> <code> BUTTON1 </code> <code> MOUSE_CLICKED </code>。
 * </PRE>
 *  当按下多个鼠标按钮时,每次按,释放和单击都会产生一个单独的事件。
 * <P>
 *  例如,如果用户按<b>按钮1 </b>后跟<b>按钮2 </b>,然后按相同顺序释放它们,则会生成以下事件序列：
 * <PRE>
 *  <b> </b> <b> <b> </b> <b> </b> <b>代码> MOUSE_PRESSED </code>：<code> BUTTON2_MASK </code> <code> BUTTO
 * N2_MASK </code> <code> BUTTON2 </code> <code> MOUSE_RELEASED </code>代码> MOUSE_CLICKED </code>：<code> 
 * BUTTON1_MASK </code> <code> BUTTON1_MASK </code> <code> BUTTON1 </code>代码> MOUSE_CLICKED </code>：<code>
 *  BUTTON2_MASK </code> <code> BUTTON2 </code>。
 * </PRE>
 *  如果首先释放<b>按钮2 </b>,则<code> BUTTON2_MASK </code>的<code> MOUSE_RELEASED </code> / <code> MOUSE_CLICKED 
 * </code>对先到达, <code> BUTTON1_MASK </code>。
 * <p>
 * 添加了一些额外的鼠标按钮,以扩展由以下常数表示的标准按钮组：{@ code BUTTON1},{@code BUTTON2}和{@code BUTTON3}。
 * 额外按钮没有分配的{@code BUTTONx}常数,以及它们的按钮掩码未分配{@code BUTTONx_DOWN_MASK}常量。然而,从4开始的序数可以用作按钮号(按钮id)。
 * 通过{@link InputEvent#getMaskForButton(int)getMaskForButton(button)}方法获得的值可以用作按钮掩码。
 * <p>
 *  {@code MOUSE_DRAGGED}事件传递到{@code Component},其中按下鼠标按钮,直到鼠标按钮释放(无论鼠标位置是否在{@code Component}的边界内)。
 * 由于平台相关的Drag&amp; Drop实现,{@code MOUSE_DRAGGED}事件可能不会在本地拖放操作期间传送。
 * 
 *  在多屏环境中,即使鼠标位置在与<code> Component </code>相关联的<code> GraphicsConfiguration </code>的边界之外,鼠标拖动事件也会传递到<code>
 *  Component </code> >。
 * 但是,在这种情况下,鼠标拖动事件的报告位置可能与实际鼠标位置不同：。
 * <ul>
 *  <li>在没有虚拟设备的多屏环境中：
 * <br>
 * 所报告的鼠标拖拽事件的坐标被修剪以适合与<code> Component </code>相关联的<code> GraphicsConfiguration </code>的边界内。
 *  <li>在具有虚拟设备的多屏环境中：。
 * <br>
 *  所报告的鼠标拖动事件的坐标被剪切以适合与<code> Component </code>相关联的虚拟设备的边界内。
 * </ul>
 * <p>
 *  如果任何特定{@code MouseEvent}实例的{@code id}参数不在{@code MOUSE_FIRST}到{@code MOUSE_LAST} -1({@code MOUSE_WHEEL}
 * )的范围内,则会导致未指定的行为可接受)。
 * 
 * 
 * @author Carl Quinn
 *
 * @see MouseAdapter
 * @see MouseListener
 * @see MouseMotionAdapter
 * @see MouseMotionListener
 * @see MouseWheelListener
 * @see <a href="https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html">Tutorial: Writing a Mouse Listener</a>
 * @see <a href="https://docs.oracle.com/javase/tutorial/uiswing/events/mousemotionlistener.html">Tutorial: Writing a Mouse Motion Listener</a>
 *
 * @since 1.1
 */
public class MouseEvent extends InputEvent {

    /**
     * The first number in the range of ids used for mouse events.
     * <p>
     *  用于鼠标事件的ids范围中的第一个数字。
     * 
     */
    public static final int MOUSE_FIRST         = 500;

    /**
     * The last number in the range of ids used for mouse events.
     * <p>
     *  用于鼠标事件的ids范围中的最后一个数字。
     * 
     */
    public static final int MOUSE_LAST          = 507;

    /**
     * The "mouse clicked" event. This <code>MouseEvent</code>
     * occurs when a mouse button is pressed and released.
     * <p>
     *  "鼠标点击"事件。当按下并释放鼠标按钮时,会出现<code> MouseEvent </code>。
     * 
     */
    public static final int MOUSE_CLICKED = MOUSE_FIRST;

    /**
     * The "mouse pressed" event. This <code>MouseEvent</code>
     * occurs when a mouse button is pushed down.
     * <p>
     *  "鼠标按下"事件。这个<code> MouseEvent </code>在鼠标按钮被按下时发生。
     * 
     */
    public static final int MOUSE_PRESSED = 1 + MOUSE_FIRST; //Event.MOUSE_DOWN

    /**
     * The "mouse released" event. This <code>MouseEvent</code>
     * occurs when a mouse button is let up.
     * <p>
     *  "鼠标释放"事件。这个<code> MouseEvent </code>发生时,鼠标按钮放开。
     * 
     */
    public static final int MOUSE_RELEASED = 2 + MOUSE_FIRST; //Event.MOUSE_UP

    /**
     * The "mouse moved" event. This <code>MouseEvent</code>
     * occurs when the mouse position changes.
     * <p>
     *  "鼠标移动"事件。当鼠标位置改变时,会出现<code> MouseEvent </code>。
     * 
     */
    public static final int MOUSE_MOVED = 3 + MOUSE_FIRST; //Event.MOUSE_MOVE

    /**
     * The "mouse entered" event. This <code>MouseEvent</code>
     * occurs when the mouse cursor enters the unobscured part of component's
     * geometry.
     * <p>
     *  "鼠标输入"事件。当鼠标光标进入组件几何的未遮挡部分时,会出现<code> MouseEvent </code>。
     * 
     */
    public static final int MOUSE_ENTERED = 4 + MOUSE_FIRST; //Event.MOUSE_ENTER

    /**
     * The "mouse exited" event. This <code>MouseEvent</code>
     * occurs when the mouse cursor exits the unobscured part of component's
     * geometry.
     * <p>
     *  "鼠标退出"事件。当鼠标光标退出组件几何体的未遮挡部分时,会发生此<code> MouseEvent </code>。
     * 
     */
    public static final int MOUSE_EXITED = 5 + MOUSE_FIRST; //Event.MOUSE_EXIT

    /**
     * The "mouse dragged" event. This <code>MouseEvent</code>
     * occurs when the mouse position changes while a mouse button is pressed.
     * <p>
     * "鼠标拖动"事件。当鼠标按钮按下时鼠标位置改变时,会出现<code> MouseEvent </code>。
     * 
     */
    public static final int MOUSE_DRAGGED = 6 + MOUSE_FIRST; //Event.MOUSE_DRAG

    /**
     * The "mouse wheel" event.  This is the only <code>MouseWheelEvent</code>.
     * It occurs when a mouse equipped with a wheel has its wheel rotated.
     * <p>
     *  "鼠标滚轮"事件。这是唯一的<code> MouseWheelEvent </code>。当配备有轮子的鼠标的轮子旋转时,会发生这种情况。
     * 
     * 
     * @since 1.4
     */
    public static final int MOUSE_WHEEL = 7 + MOUSE_FIRST;

    /**
     * Indicates no mouse buttons; used by {@link #getButton}.
     * <p>
     *  表示没有鼠标按钮;由{@link #getButton}使用。
     * 
     * 
     * @since 1.4
     */
    public static final int NOBUTTON = 0;

    /**
     * Indicates mouse button #1; used by {@link #getButton}.
     * <p>
     *  表示鼠标按钮#1;由{@link #getButton}使用。
     * 
     * 
     * @since 1.4
     */
    public static final int BUTTON1 = 1;

    /**
     * Indicates mouse button #2; used by {@link #getButton}.
     * <p>
     *  表示鼠标按钮#2;由{@link #getButton}使用。
     * 
     * 
     * @since 1.4
     */
    public static final int BUTTON2 = 2;

    /**
     * Indicates mouse button #3; used by {@link #getButton}.
     * <p>
     *  表示鼠标按钮#3;由{@link #getButton}使用。
     * 
     * 
     * @since 1.4
     */
    public static final int BUTTON3 = 3;

    /**
     * The mouse event's x coordinate.
     * The x value is relative to the component that fired the event.
     *
     * <p>
     *  鼠标事件的x坐标。 x值相对于触发事件的组件。
     * 
     * 
     * @serial
     * @see #getX()
     */
    int x;

    /**
     * The mouse event's y coordinate.
     * The y value is relative to the component that fired the event.
     *
     * <p>
     *  鼠标事件的y坐标。 y值相对于触发事件的组件。
     * 
     * 
     * @serial
     * @see #getY()
     */
    int y;

    /**
     * The mouse event's x absolute coordinate.
     * In a virtual device multi-screen environment in which the
     * desktop area could span multiple physical screen devices,
     * this coordinate is relative to the virtual coordinate system.
     * Otherwise, this coordinate is relative to the coordinate system
     * associated with the Component's GraphicsConfiguration.
     *
     * <p>
     *  鼠标事件的x绝对坐标。在其中桌面区域可以跨越多个物理屏幕设备的虚拟设备多屏幕环境中,该坐标相对于虚拟坐标系。否则,此坐标相对于与组件的GraphicsConfiguration相关联的坐标系。
     * 
     * 
     * @serial
   */
    private int xAbs;

    /**
     * The mouse event's y absolute coordinate.
     * In a virtual device multi-screen environment in which the
     * desktop area could span multiple physical screen devices,
     * this coordinate is relative to the virtual coordinate system.
     * Otherwise, this coordinate is relative to the coordinate system
     * associated with the Component's GraphicsConfiguration.
     *
     * <p>
     *  鼠标事件的y绝对坐标。在其中桌面区域可以跨越多个物理屏幕设备的虚拟设备多屏幕环境中,该坐标相对于虚拟坐标系。否则,此坐标相对于与组件的GraphicsConfiguration相关联的坐标系。
     * 
     * 
     * @serial
     */
    private int yAbs;

    /**
     * Indicates the number of quick consecutive clicks of
     * a mouse button.
     * clickCount will be valid for only three mouse events :<BR>
     * <code>MOUSE_CLICKED</code>,
     * <code>MOUSE_PRESSED</code> and
     * <code>MOUSE_RELEASED</code>.
     * For the above, the <code>clickCount</code> will be at least 1.
     * For all other events the count will be 0.
     *
     * <p>
     * 表示快速连续点击鼠标按钮的次数。
     *  clickCount只对三个鼠标事件有效：<BR> <code> MOUSE_CLICKED </code>,<code> MOUSE_PRESSED </code>和<code> MOUSE_REL
     * EASED </code>。
     * 表示快速连续点击鼠标按钮的次数。对于上述,<code> clickCount </code>将至少为1.对于所有其他事件,计数将为0。
     * 
     * 
     * @serial
     * @see #getClickCount()
     */
    int clickCount;

    /**
     * Indicates which, if any, of the mouse buttons has changed state.
     *
     * The valid values are ranged from 0 to the value returned by the
     * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} method.
     * This range already includes constants {@code NOBUTTON}, {@code BUTTON1},
     * {@code BUTTON2}, and {@code BUTTON3}
     * if these buttons are present. So it is allowed to use these constants too.
     * For example, for a mouse with two buttons this field may contain the following values:
     * <ul>
     * <li> 0 ({@code NOBUTTON})
     * <li> 1 ({@code BUTTON1})
     * <li> 2 ({@code BUTTON2})
     * </ul>
     * If a mouse has 5 buttons, this field may contain the following values:
     * <ul>
     * <li> 0 ({@code NOBUTTON})
     * <li> 1 ({@code BUTTON1})
     * <li> 2 ({@code BUTTON2})
     * <li> 3 ({@code BUTTON3})
     * <li> 4
     * <li> 5
     * </ul>
     * If support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled()} disabled by Java
     * then the field may not contain the value larger than {@code BUTTON3}.
     * <p>
     *  指示鼠标按钮中的哪些(如果有)已更改状态。
     * 
     *  有效值的范围从0到{@link java.awt.MouseInfo#getNumberOfButtons()MouseInfo.getNumberOfButtons()}方法返回的值。
     * 如果这些按钮存在,则此范围已包含常数{@code NOBUTTON},{@code BUTTON1},{@code BUTTON2}和{@code BUTTON3}。所以也允许使用这些常量。
     * 例如,对于具有两个按钮的鼠标,此字段可以包含以下值：。
     * <ul>
     *  <li> 0({@code NOBUTTON})<li> 1({@code BUTTON1})<li> 2({@code BUTTON2})
     * </ul>
     *  如果鼠标有5个按钮,则此字段可能包含以下值：
     * <ul>
     *  <li> 0({@code BUTTON3})<li> 1({@code BUTTON1})<li> 2({@code BUTTON2} > 5
     * </ul>
     *  如果支持扩展鼠标按钮是{@link Toolkit#areExtraMouseButtonsEnabled()}由Java禁用,那么该字段可能不包含大于{@code BUTTON3}的值。
     * 
     * 
     * @serial
     * @see #getButton()
     * @see java.awt.Toolkit#areExtraMouseButtonsEnabled()
     */
    int button;

    /**
     * A property used to indicate whether a Popup Menu
     * should appear  with a certain gestures.
     * If <code>popupTrigger</code> = <code>false</code>,
     * no popup menu should appear.  If it is <code>true</code>
     * then a popup menu should appear.
     *
     * <p>
     *  用于指示弹出菜单是否应该与某些手势一起显示的属性。如果<code> popupTrigger </code> = <code> false </code>,则不会出现弹出式菜单。
     * 如果它是<code> true </code>,那么应该会出现一个弹出菜单。
     * 
     * 
     * @serial
     * @see java.awt.PopupMenu
     * @see #isPopupTrigger()
     */
    boolean popupTrigger = false;

    /*
     * JDK 1.1 serialVersionUID
     * <p>
     * JDK 1.1 serialVersionUID
     * 
     */
    private static final long serialVersionUID = -991214153494842848L;

    /**
     * A number of buttons available on the mouse at the {@code Toolkit} machinery startup.
     * <p>
     *  在{@code Toolkit}机械启动时,鼠标上有许多按钮。
     * 
     */
    private static int cachedNumberOfButtons;

    static {
        /* ensure that the necessary native libraries are loaded */
        NativeLibLoader.loadLibraries();
        if (!GraphicsEnvironment.isHeadless()) {
            initIDs();
        }
        final Toolkit tk = Toolkit.getDefaultToolkit();
        if (tk instanceof SunToolkit) {
            cachedNumberOfButtons = ((SunToolkit)tk).getNumberOfButtons();
        } else {
            //It's expected that some toolkits (Headless,
            //whatever besides SunToolkit) could also operate.
            cachedNumberOfButtons = 3;
        }
    }

    /**
     * Initialize JNI field and method IDs for fields that may be
     *  accessed from C.
     * <p>
     *  初始化可从C访问的字段的JNI字段和方法ID。
     * 
     */
    private static native void initIDs();

    /**
     * Returns the absolute x, y position of the event.
     * In a virtual device multi-screen environment in which the
     * desktop area could span multiple physical screen devices,
     * these coordinates are relative to the virtual coordinate system.
     * Otherwise, these coordinates are relative to the coordinate system
     * associated with the Component's GraphicsConfiguration.
     *
     * <p>
     *  返回事件的绝对x,y位置。在其中桌面区域可以跨越多个物理屏幕设备的虚拟设备多屏幕环境中,这些坐标是相对于虚拟坐标系的。
     * 否则,这些坐标相对于与组件的GraphicsConfiguration相关联的坐标系。
     * 
     * 
     * @return a <code>Point</code> object containing the absolute  x
     *  and y coordinates.
     *
     * @see java.awt.GraphicsConfiguration
     * @since 1.6
     */
    public Point getLocationOnScreen(){
      return new Point(xAbs, yAbs);
    }

    /**
     * Returns the absolute horizontal x position of the event.
     * In a virtual device multi-screen environment in which the
     * desktop area could span multiple physical screen devices,
     * this coordinate is relative to the virtual coordinate system.
     * Otherwise, this coordinate is relative to the coordinate system
     * associated with the Component's GraphicsConfiguration.
     *
     * <p>
     *  返回事件的绝对水平x位置。在其中桌面区域可以跨越多个物理屏幕设备的虚拟设备多屏幕环境中,该坐标相对于虚拟坐标系。否则,此坐标相对于与组件的GraphicsConfiguration相关联的坐标系。
     * 
     * 
     * @return x  an integer indicating absolute horizontal position.
     *
     * @see java.awt.GraphicsConfiguration
     * @since 1.6
     */
    public int getXOnScreen() {
        return xAbs;
    }

    /**
     * Returns the absolute vertical y position of the event.
     * In a virtual device multi-screen environment in which the
     * desktop area could span multiple physical screen devices,
     * this coordinate is relative to the virtual coordinate system.
     * Otherwise, this coordinate is relative to the coordinate system
     * associated with the Component's GraphicsConfiguration.
     *
     * <p>
     *  返回事件的绝对垂直y位置。在其中桌面区域可以跨越多个物理屏幕设备的虚拟设备多屏幕环境中,该坐标相对于虚拟坐标系。否则,此坐标相对于与组件的GraphicsConfiguration相关联的坐标系。
     * 
     * 
     * @return y  an integer indicating absolute vertical position.
     *
     * @see java.awt.GraphicsConfiguration
     * @since 1.6
     */
    public int getYOnScreen() {
        return yAbs;
    }

    /**
     * Constructs a <code>MouseEvent</code> object with the
     * specified source component,
     * type, time, modifiers, coordinates, click count, popupTrigger flag,
     * and button number.
     * <p>
     * Creating an invalid event (such
     * as by using more than one of the old _MASKs, or modifier/button
     * values which don't match) results in unspecified behavior.
     * An invocation of the form
     * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger, button)</tt>
     * behaves in exactly the same way as the invocation
     * <tt> {@link #MouseEvent(Component, int, long, int, int, int,
     * int, int, int, boolean, int) MouseEvent}(source, id, when, modifiers,
     * x, y, xAbs, yAbs, clickCount, popupTrigger, button)</tt>
     * where xAbs and yAbs defines as source's location on screen plus
     * relative coordinates x and y.
     * xAbs and yAbs are set to zero if the source is not showing.
     * This method throws an
     * <code>IllegalArgumentException</code> if <code>source</code>
     * is <code>null</code>.
     *
     * <p>
     *  构造具有指定源组件,类型,时间,修饰符,坐标,点击计数,popupTrigger标志和按钮编号的<code> MouseEvent </code>对象。
     * <p>
     * 创建无效事件(例如,通过使用多个旧的_MASK或不匹配的修饰符/按钮值)会导致未指定的行为。
     * 调用形式<tt> MouseEvent(source,id,when,modifiers,x,y,clickCount,popupTrigger,button)</tt>的行为方式与调用<tt> {@link #MouseEvent Component,int,long,int,int,int,int,int,int,boolean,int)MouseEvent}
     * (source,id,when,modifiers,x,y,xAbs,yAbs,clickCount,popupTrigger,button)</tt >其中xAbs和yAbs定义为屏幕上源的位置加上相
     * 对坐标x和y。
     * 创建无效事件(例如,通过使用多个旧的_MASK或不匹配的修饰符/按钮值)会导致未指定的行为。如果源不显示,xAbs和yAbs设置为零。
     * 如果<code> source </code>是<code> null </code>,此方法会抛出<code> IllegalArgumentException </code>。
     * 
     * 
     * @param source       The <code>Component</code> that originated the event
     * @param id              An integer indicating the type of event.
     *                     For information on allowable values, see
     *                     the class description for {@link MouseEvent}
     * @param when         A long integer that gives the time the event occurred.
     *                     Passing negative or zero value
     *                     is not recommended
     * @param modifiers    a modifier mask describing the modifier keys and mouse
     *                     buttons (for example, shift, ctrl, alt, and meta) that
     *                     are down during the event.
     *                     Only extended modifiers are allowed to be used as a
     *                     value for this parameter (see the {@link InputEvent#getModifiersEx}
     *                     class for the description of extended modifiers).
     *                     Passing negative parameter
     *                     is not recommended.
     *                     Zero value means that no modifiers were passed
     * @param x            The horizontal x coordinate for the mouse location.
     *                       It is allowed to pass negative values
     * @param y            The vertical y coordinate for the mouse location.
     *                       It is allowed to pass negative values
     * @param clickCount   The number of mouse clicks associated with event.
     *                       Passing negative value
     *                       is not recommended
     * @param popupTrigger A boolean that equals {@code true} if this event
     *                     is a trigger for a popup menu
     * @param button       An integer that indicates, which of the mouse buttons has
     *                     changed its state.
     * The following rules are applied to this parameter:
     * <ul>
     * <li>If support for the extended mouse buttons is
     * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * then it is allowed to create {@code MouseEvent} objects only with the standard buttons:
     * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, and
     * {@code BUTTON3}.
     * <li> If support for the extended mouse buttons is
     * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
     * then it is allowed to create {@code MouseEvent} objects with
     * the standard buttons.
     * In case the support for extended mouse buttons is
     * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java, then
     * in addition to the standard buttons, {@code MouseEvent} objects can be created
     * using buttons from the range starting from 4 to
     * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}
     * if the mouse has more than three buttons.
     * </ul>
     * @throws IllegalArgumentException if {@code button} is less then zero
     * @throws IllegalArgumentException if <code>source</code> is null
     * @throws IllegalArgumentException if {@code button} is greater then BUTTON3 and the support for extended mouse buttons is
     *                                  {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * @throws IllegalArgumentException if {@code button} is greater then the
     *                                  {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} and the support
     *                                  for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled}
     *                                  by Java
     * @throws IllegalArgumentException if an invalid <code>button</code>
     *            value is passed in
     * @throws IllegalArgumentException if <code>source</code> is null
     * @see #getSource()
     * @see #getID()
     * @see #getWhen()
     * @see #getModifiers()
     * @see #getX()
     * @see #getY()
     * @see #getClickCount()
     * @see #isPopupTrigger()
     * @see #getButton()
     * @since 1.4
     */
    public MouseEvent(Component source, int id, long when, int modifiers,
                      int x, int y, int clickCount, boolean popupTrigger,
                      int button)
    {
        this(source, id, when, modifiers, x, y, 0, 0, clickCount, popupTrigger, button);
        Point eventLocationOnScreen = new Point(0, 0);
        try {
          eventLocationOnScreen = source.getLocationOnScreen();
          this.xAbs = eventLocationOnScreen.x + x;
          this.yAbs = eventLocationOnScreen.y + y;
        } catch (IllegalComponentStateException e){
          this.xAbs = 0;
          this.yAbs = 0;
        }
    }

    /**
     * Constructs a <code>MouseEvent</code> object with the
     * specified source component,
     * type, modifiers, coordinates, click count, and popupTrigger flag.
     * An invocation of the form
     * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger)</tt>
     * behaves in exactly the same way as the invocation
     * <tt> {@link #MouseEvent(Component, int, long, int, int, int,
     * int, int, int, boolean, int) MouseEvent}(source, id, when, modifiers,
     * x, y, xAbs, yAbs, clickCount, popupTrigger, MouseEvent.NOBUTTON)</tt>
     * where xAbs and yAbs defines as source's location on screen plus
     * relative coordinates x and y.
     * xAbs and yAbs are set to zero if the source is not showing.
     * This method throws an <code>IllegalArgumentException</code>
     * if <code>source</code> is <code>null</code>.
     *
     * <p>
     * 构造具有指定源组件,类型,修饰符,坐标,点击计数和popupTrigger标志的<code> MouseEvent </code>对象。
     * 调用形式<tt> MouseEvent(source,id,when,modifiers,x,y,clickCount,popupTrigger)</tt>的行为方式与调用<tt> {@link #MouseEvent int,long,int,int,int,int,int,int,boolean,int)MouseEvent}
     * (source,id,when,modifiers,x,y,xAbs,yAbs,clickCount,popupTrigger,MouseEvent.NOBUTTON)</tt >其中xAbs和yAbs
     * 定义为屏幕上源的位置加上相对坐标x和y。
     * 构造具有指定源组件,类型,修饰符,坐标,点击计数和popupTrigger标志的<code> MouseEvent </code>对象。如果源不显示,xAbs和yAbs设置为零。
     * 如果<code> source </code>是<code> null </code>,此方法会抛出<code> IllegalArgumentException </code>。
     * 
     * 
     * @param source       The <code>Component</code> that originated the event
     * @param id              An integer indicating the type of event.
     *                     For information on allowable values, see
     *                     the class description for {@link MouseEvent}
     * @param when         A long integer that gives the time the event occurred.
     *                     Passing negative or zero value
     *                     is not recommended
     * @param modifiers    a modifier mask describing the modifier keys and mouse
     *                     buttons (for example, shift, ctrl, alt, and meta) that
     *                     are down during the event.
     *                     Only extended modifiers are allowed to be used as a
     *                     value for this parameter (see the {@link InputEvent#getModifiersEx}
     *                     class for the description of extended modifiers).
     *                     Passing negative parameter
     *                     is not recommended.
     *                     Zero value means that no modifiers were passed
     * @param x            The horizontal x coordinate for the mouse location.
     *                       It is allowed to pass negative values
     * @param y            The vertical y coordinate for the mouse location.
     *                       It is allowed to pass negative values
     * @param clickCount   The number of mouse clicks associated with event.
     *                       Passing negative value
     *                       is not recommended
     * @param popupTrigger A boolean that equals {@code true} if this event
     *                     is a trigger for a popup menu
     * @throws IllegalArgumentException if <code>source</code> is null
     * @see #getSource()
     * @see #getID()
     * @see #getWhen()
     * @see #getModifiers()
     * @see #getX()
     * @see #getY()
     * @see #getClickCount()
     * @see #isPopupTrigger()
     */
     public MouseEvent(Component source, int id, long when, int modifiers,
                      int x, int y, int clickCount, boolean popupTrigger) {
        this(source, id, when, modifiers, x, y, clickCount, popupTrigger, NOBUTTON);
     }


    /* if the button is an extra button and it is released or clicked then in Xsystem its state
    /* <p>
    /* 
       is not modified. Exclude this button number from ExtModifiers mask.*/
    transient private boolean shouldExcludeButtonFromExtModifiers = false;

    /**
     * {@inheritDoc}
     * <p>
     *  {@inheritDoc}
     * 
     */
    public int getModifiersEx() {
        int tmpModifiers = modifiers;
        if (shouldExcludeButtonFromExtModifiers) {
            tmpModifiers &= ~(InputEvent.getMaskForButton(getButton()));
        }
        return tmpModifiers & ~JDK_1_3_MODIFIERS;
    }

    /**
     * Constructs a <code>MouseEvent</code> object with the
     * specified source component,
     * type, time, modifiers, coordinates, absolute coordinates, click count, popupTrigger flag,
     * and button number.
     * <p>
     * Creating an invalid event (such
     * as by using more than one of the old _MASKs, or modifier/button
     * values which don't match) results in unspecified behavior.
     * Even if inconsistent values for relative and absolute coordinates are
     * passed to the constructor, the mouse event instance is still
     * created and no exception is thrown.
     * This method throws an
     * <code>IllegalArgumentException</code> if <code>source</code>
     * is <code>null</code>.
     *
     * <p>
     *  构造具有指定的源组件,类型,时间,修饰符,坐标,绝对坐标,点击计数,popupTrigger标志和按钮编号的<code> MouseEvent </code>对象。
     * <p>
     *  创建无效事件(例如,通过使用多个旧的_MASK或不匹配的修饰符/按钮值)会导致未指定的行为。即使将相对和绝对坐标的不一致值传递给构造函数,仍会创建鼠标事件实例,并且不会抛出任何异常。
     * 如果<code> source </code>是<code> null </code>,此方法会抛出<code> IllegalArgumentException </code>。
     * 
     * 
     * @param source       The <code>Component</code> that originated the event
     * @param id              An integer indicating the type of event.
     *                     For information on allowable values, see
     *                     the class description for {@link MouseEvent}
     * @param when         A long integer that gives the time the event occurred.
     *                     Passing negative or zero value
     *                     is not recommended
     * @param modifiers    a modifier mask describing the modifier keys and mouse
     *                     buttons (for example, shift, ctrl, alt, and meta) that
     *                     are down during the event.
     *                     Only extended modifiers are allowed to be used as a
     *                     value for this parameter (see the {@link InputEvent#getModifiersEx}
     *                     class for the description of extended modifiers).
     *                     Passing negative parameter
     *                     is not recommended.
     *                     Zero value means that no modifiers were passed
     * @param x            The horizontal x coordinate for the mouse location.
     *                       It is allowed to pass negative values
     * @param y            The vertical y coordinate for the mouse location.
     *                       It is allowed to pass negative values
     * @param xAbs           The absolute horizontal x coordinate for the mouse location
     *                       It is allowed to pass negative values
     * @param yAbs           The absolute vertical y coordinate for the mouse location
     *                       It is allowed to pass negative values
     * @param clickCount   The number of mouse clicks associated with event.
     *                       Passing negative value
     *                       is not recommended
     * @param popupTrigger A boolean that equals {@code true} if this event
     *                     is a trigger for a popup menu
     * @param button       An integer that indicates, which of the mouse buttons has
     *                     changed its state.
     * The following rules are applied to this parameter:
     * <ul>
     * <li>If support for the extended mouse buttons is
     * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * then it is allowed to create {@code MouseEvent} objects only with the standard buttons:
     * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, and
     * {@code BUTTON3}.
     * <li> If support for the extended mouse buttons is
     * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
     * then it is allowed to create {@code MouseEvent} objects with
     * the standard buttons.
     * In case the support for extended mouse buttons is
     * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java, then
     * in addition to the standard buttons, {@code MouseEvent} objects can be created
     * using buttons from the range starting from 4 to
     * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}
     * if the mouse has more than three buttons.
     * </ul>
     * @throws IllegalArgumentException if {@code button} is less then zero
     * @throws IllegalArgumentException if <code>source</code> is null
     * @throws IllegalArgumentException if {@code button} is greater then BUTTON3 and the support for extended mouse buttons is
     *                                  {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * @throws IllegalArgumentException if {@code button} is greater then the
     *                                  {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} and the support
     *                                  for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled}
     *                                  by Java
     * @throws IllegalArgumentException if an invalid <code>button</code>
     *            value is passed in
     * @throws IllegalArgumentException if <code>source</code> is null
     * @see #getSource()
     * @see #getID()
     * @see #getWhen()
     * @see #getModifiers()
     * @see #getX()
     * @see #getY()
     * @see #getXOnScreen()
     * @see #getYOnScreen()
     * @see #getClickCount()
     * @see #isPopupTrigger()
     * @see #getButton()
     * @see #button
     * @see Toolkit#areExtraMouseButtonsEnabled()
     * @see java.awt.MouseInfo#getNumberOfButtons()
     * @see InputEvent#getMaskForButton(int)
     * @since 1.6
     */
    public MouseEvent(Component source, int id, long when, int modifiers,
                      int x, int y, int xAbs, int yAbs,
                      int clickCount, boolean popupTrigger, int button)
    {
        super(source, id, when, modifiers);
        this.x = x;
        this.y = y;
        this.xAbs = xAbs;
        this.yAbs = yAbs;
        this.clickCount = clickCount;
        this.popupTrigger = popupTrigger;
        if (button < NOBUTTON){
            throw new IllegalArgumentException("Invalid button value :" + button);
        }
        if (button > BUTTON3) {
            if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){
                throw new IllegalArgumentException("Extra mouse events are disabled " + button);
            } else {
                if (button > cachedNumberOfButtons) {
                    throw new IllegalArgumentException("Nonexistent button " + button);
                }
            }
            // XToolkit: extra buttons are not reporting about their state correctly.
            // Being pressed they report the state=0 both on the press and on the release.
            // For 1-3 buttons the state value equals zero on press and non-zero on release.
            // Other modifiers like Shift, ALT etc seem report well with extra buttons.
            // The problem reveals as follows: one button is pressed and then another button is pressed and released.
            // So, the getModifiersEx() would not be zero due to a first button and we will skip this modifier.
            // This may have to be moved into the peer code instead if possible.

            if (getModifiersEx() != 0) { //There is at least one more button in a pressed state.
                if (id == MouseEvent.MOUSE_RELEASED || id == MouseEvent.MOUSE_CLICKED){
                    shouldExcludeButtonFromExtModifiers = true;
                }
            }
        }

        this.button = button;

        if ((getModifiers() != 0) && (getModifiersEx() == 0)) {
            setNewModifiers();
        } else if ((getModifiers() == 0) &&
                   (getModifiersEx() != 0 || button != NOBUTTON) &&
                   (button <= BUTTON3))
        {
            setOldModifiers();
        }
    }

    /**
     * Returns the horizontal x position of the event relative to the
     * source component.
     *
     * <p>
     *  返回事件相对于源组件的水平x位置。
     * 
     * 
     * @return x  an integer indicating horizontal position relative to
     *            the component
     */
    public int getX() {
        return x;
    }

    /**
     * Returns the vertical y position of the event relative to the
     * source component.
     *
     * <p>
     * 返回事件相对于源组件的垂直y位置。
     * 
     * 
     * @return y  an integer indicating vertical position relative to
     *            the component
     */
    public int getY() {
        return y;
    }

    /**
     * Returns the x,y position of the event relative to the source component.
     *
     * <p>
     *  返回事件相对于源组件的x,y位置。
     * 
     * 
     * @return a <code>Point</code> object containing the x and y coordinates
     *         relative to the source component
     *
     */
    public Point getPoint() {
        int x;
        int y;
        synchronized (this) {
            x = this.x;
            y = this.y;
        }
        return new Point(x, y);
    }

    /**
     * Translates the event's coordinates to a new position
     * by adding specified <code>x</code> (horizontal) and <code>y</code>
     * (vertical) offsets.
     *
     * <p>
     *  通过添加指定的<code> x </code>(水平)和<code> y </code>(垂直)偏移将事件的坐标转换到新位置。
     * 
     * 
     * @param x the horizontal x value to add to the current x
     *          coordinate position
     * @param y the vertical y value to add to the current y
                coordinate position
     */
    public synchronized void translatePoint(int x, int y) {
        this.x += x;
        this.y += y;
    }

    /**
     * Returns the number of mouse clicks associated with this event.
     *
     * <p>
     *  返回与此事件相关联的鼠标点击次数。
     * 
     * 
     * @return integer value for the number of clicks
     */
    public int getClickCount() {
        return clickCount;
    }

    /**
     * Returns which, if any, of the mouse buttons has changed state.
     * The returned value is ranged
     * from 0 to the {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}
     * value.
     * The returned value includes at least the following constants:
     * <ul>
     * <li> {@code NOBUTTON}
     * <li> {@code BUTTON1}
     * <li> {@code BUTTON2}
     * <li> {@code BUTTON3}
     * </ul>
     * It is allowed to use those constants to compare with the returned button number in the application.
     * For example,
     * <pre>
     * if (anEvent.getButton() == MouseEvent.BUTTON1) {
     * </pre>
     * In particular, for a mouse with one, two, or three buttons this method may return the following values:
     * <ul>
     * <li> 0 ({@code NOBUTTON})
     * <li> 1 ({@code BUTTON1})
     * <li> 2 ({@code BUTTON2})
     * <li> 3 ({@code BUTTON3})
     * </ul>
     * Button numbers greater then {@code BUTTON3} have no constant identifier. So if a mouse with five buttons is
     * installed, this method may return the following values:
     * <ul>
     * <li> 0 ({@code NOBUTTON})
     * <li> 1 ({@code BUTTON1})
     * <li> 2 ({@code BUTTON2})
     * <li> 3 ({@code BUTTON3})
     * <li> 4
     * <li> 5
     * </ul>
     * <p>
     * Note: If support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * then the AWT event subsystem does not produce mouse events for the extended mouse
     * buttons. So it is not expected that this method returns anything except {@code NOBUTTON}, {@code BUTTON1},
     * {@code BUTTON2}, {@code BUTTON3}.
     *
     * <p>
     *  返回鼠标按钮(如果有)是否已更改状态。
     * 返回值的范围从0到{@link java.awt.MouseInfo#getNumberOfButtons()MouseInfo.getNumberOfButtons()}值。
     * 返回的值至少包括以下常量：。
     * <ul>
     *  <li> {@ code NOBUTTON} <li> {@code BUTTON1} <li> {@code BUTTON2} <li> {@code BUTTON3}
     * </ul>
     *  允许使用那些常量来与应用程序中返回的按钮号进行比较。例如,
     * <pre>
     *  if(anEvent.getButton()== MouseEvent.BUTTON1){
     * </pre>
     *  特别地,对于具有一个,两个或三个按钮的鼠标,该方法可以返回以下值：
     * <ul>
     *  <li> 0({@code NOBUTTON})<li> 1({@code BUTTON1})<li> 2({@code BUTTON2})<li> 3
     * </ul>
     *  大于{@code BUTTON3}的按钮编号没有常数标识符。因此,如果安装了具有五个按钮的鼠标,则此方法可能返回以下值：
     * <ul>
     *  <li> 0({@code BUTTON3})<li> 1({@code BUTTON1})<li> 2({@code BUTTON2} > 5
     * </ul>
     * <p>
     * 注意：如果Java支持扩展鼠标按钮{@link Toolkit#areExtraMouseButtonsEnabled()disabled},则AWT事件子系统不会为扩展鼠标按钮生成鼠标事件。
     * 因此,不希望此方法返回除{@code NOBUTTON},{@code BUTTON1},{@code BUTTON2},{@code BUTTON3}之外的任何内容。
     * 
     * 
     * @return one of the values from 0 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}
     *         if support for the extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java.
     *         That range includes {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, {@code BUTTON3};
     *         <br>
     *         {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2} or {@code BUTTON3}
     *         if support for the extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * @since 1.4
     * @see Toolkit#areExtraMouseButtonsEnabled()
     * @see java.awt.MouseInfo#getNumberOfButtons()
     * @see #MouseEvent(Component, int, long, int, int, int, int, int, int, boolean, int)
     * @see InputEvent#getMaskForButton(int)
     */
    public int getButton() {
        return button;
    }

    /**
     * Returns whether or not this mouse event is the popup menu
     * trigger event for the platform.
     * <p><b>Note</b>: Popup menus are triggered differently
     * on different systems. Therefore, <code>isPopupTrigger</code>
     * should be checked in both <code>mousePressed</code>
     * and <code>mouseReleased</code>
     * for proper cross-platform functionality.
     *
     * <p>
     *  返回此鼠标事件是否为平台的弹出菜单触发事件。 <p> <b>注意</b>：弹出菜单在不同系统上的触发方式不同。
     * 因此,应在<code> mousePressed </code>和<code> mouseReleased </code>中检查<code> isPopupTrigger </code>以获得适当的跨平
     * 台功能。
     *  返回此鼠标事件是否为平台的弹出菜单触发事件。 <p> <b>注意</b>：弹出菜单在不同系统上的触发方式不同。
     * 
     * 
     * @return boolean, true if this event is the popup menu trigger
     *         for this platform
     */
    public boolean isPopupTrigger() {
        return popupTrigger;
    }

    /**
     * Returns a <code>String</code> instance describing the modifier keys and
     * mouse buttons that were down during the event, such as "Shift",
     * or "Ctrl+Shift". These strings can be localized by changing
     * the <code>awt.properties</code> file.
     * <p>
     * Note that the <code>InputEvent.ALT_MASK</code> and
     * <code>InputEvent.BUTTON2_MASK</code> have equal values,
     * so the "Alt" string is returned for both modifiers.  Likewise,
     * the <code>InputEvent.META_MASK</code> and
     * <code>InputEvent.BUTTON3_MASK</code> have equal values,
     * so the "Meta" string is returned for both modifiers.
     * <p>
     * Note that passing negative parameter is incorrect,
     * and will cause the returning an unspecified string.
     * Zero parameter means that no modifiers were passed and will
     * cause the returning an empty string.
     * <p>
     * <p>
     *  返回描述在事件期间关闭的修饰键和鼠标按键(例如"Shift"或"Ctrl + Shift")的<code> String </code>实例。
     * 这些字符串可以通过更改<code> awt.properties </code>文件进行本地化。
     * <p>
     *  请注意,<code> InputEvent.ALT_MASK </code>和<code> InputEvent.BUTTON2_MASK </code>具有相同的值,因此为两个修饰符返回"Alt"字
     * 符串。
     * 同样,<code> InputEvent.META_MASK </code>和<code> InputEvent.BUTTON3_MASK </code>具有相同的值,因此返回两个修饰符的"Meta"字
     * 符串。
     * <p>
     *  注意,传递负参数不正确,将导致返回一个未指定的字符串。零参数意味着没有传递修饰符,并将导致返回一个空字符串。
     * <p>
     * 
     * @param modifiers A modifier mask describing the modifier keys and
     *                  mouse buttons that were down during the event
     * @return string   string text description of the combination of modifier
     *                  keys and mouse buttons that were down during the event
     * @see InputEvent#getModifiersExText(int)
     * @since 1.4
     */
    public static String getMouseModifiersText(int modifiers) {
        StringBuilder buf = new StringBuilder();
        if ((modifiers & InputEvent.ALT_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.alt", "Alt"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.META_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.meta", "Meta"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.CTRL_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.control", "Ctrl"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.shift", "Shift"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.BUTTON1_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.button1", "Button1"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.button2", "Button2"));
            buf.append("+");
        }
        if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
            buf.append(Toolkit.getProperty("AWT.button3", "Button3"));
            buf.append("+");
        }

        int mask;

        // TODO: add a toolkit field that holds a number of button on the mouse.
        // As the method getMouseModifiersText() is static and obtain
        // an integer as a parameter then we may not restrict this with the number
        // of buttons installed on the mouse.
        // It's a temporary solution. We need to somehow hold the number of buttons somewhere else.
        for (int i = 1; i <= cachedNumberOfButtons; i++){
            mask = InputEvent.getMaskForButton(i);
            if ((modifiers & mask) != 0 &&
                buf.indexOf(Toolkit.getProperty("AWT.button"+i, "Button"+i)) == -1) //1,2,3 buttons may already be there; so don't duplicate it.
            {
                buf.append(Toolkit.getProperty("AWT.button"+i, "Button"+i));
                buf.append("+");
            }
        }

        if (buf.length() > 0) {
            buf.setLength(buf.length()-1); // remove trailing '+'
        }
        return buf.toString();
    }

    /**
     * Returns a parameter string identifying this event.
     * This method is useful for event-logging and for debugging.
     *
     * <p>
     * 返回标识此事件的参数字符串。此方法对事件记录和调试非常有用。
     * 
     * 
     * @return a string identifying the event and its attributes
     */
    public String paramString() {
        StringBuilder str = new StringBuilder(80);

        switch(id) {
          case MOUSE_PRESSED:
              str.append("MOUSE_PRESSED");
              break;
          case MOUSE_RELEASED:
              str.append("MOUSE_RELEASED");
              break;
          case MOUSE_CLICKED:
              str.append("MOUSE_CLICKED");
              break;
          case MOUSE_ENTERED:
              str.append("MOUSE_ENTERED");
              break;
          case MOUSE_EXITED:
              str.append("MOUSE_EXITED");
              break;
          case MOUSE_MOVED:
              str.append("MOUSE_MOVED");
              break;
          case MOUSE_DRAGGED:
              str.append("MOUSE_DRAGGED");
              break;
          case MOUSE_WHEEL:
              str.append("MOUSE_WHEEL");
              break;
           default:
              str.append("unknown type");
        }

        // (x,y) coordinates
        str.append(",(").append(x).append(",").append(y).append(")");
        str.append(",absolute(").append(xAbs).append(",").append(yAbs).append(")");

        if (id != MOUSE_DRAGGED && id != MOUSE_MOVED){
            str.append(",button=").append(getButton());
        }

        if (getModifiers() != 0) {
            str.append(",modifiers=").append(getMouseModifiersText(modifiers));
        }

        if (getModifiersEx() != 0) {
            //Using plain "modifiers" here does show an excluded extended buttons in the string event representation.
            //getModifiersEx() solves the problem.
            str.append(",extModifiers=").append(getModifiersExText(getModifiersEx()));
        }

        str.append(",clickCount=").append(clickCount);

        return str.toString();
    }

    /**
     * Sets new modifiers by the old ones.
     * Also sets button.
     * <p>
     *  使用旧的修饰符设置新的修饰符。也设置按钮。
     * 
     */
    private void setNewModifiers() {
        if ((modifiers & BUTTON1_MASK) != 0) {
            modifiers |= BUTTON1_DOWN_MASK;
        }
        if ((modifiers & BUTTON2_MASK) != 0) {
            modifiers |= BUTTON2_DOWN_MASK;
        }
        if ((modifiers & BUTTON3_MASK) != 0) {
            modifiers |= BUTTON3_DOWN_MASK;
        }
        if (id == MOUSE_PRESSED
            || id == MOUSE_RELEASED
            || id == MOUSE_CLICKED)
        {
            if ((modifiers & BUTTON1_MASK) != 0) {
                button = BUTTON1;
                modifiers &= ~BUTTON2_MASK & ~BUTTON3_MASK;
                if (id != MOUSE_PRESSED) {
                    modifiers &= ~BUTTON1_DOWN_MASK;
                }
            } else if ((modifiers & BUTTON2_MASK) != 0) {
                button = BUTTON2;
                modifiers &= ~BUTTON1_MASK & ~BUTTON3_MASK;
                if (id != MOUSE_PRESSED) {
                    modifiers &= ~BUTTON2_DOWN_MASK;
                }
            } else if ((modifiers & BUTTON3_MASK) != 0) {
                button = BUTTON3;
                modifiers &= ~BUTTON1_MASK & ~BUTTON2_MASK;
                if (id != MOUSE_PRESSED) {
                    modifiers &= ~BUTTON3_DOWN_MASK;
                }
            }
        }
        if ((modifiers & InputEvent.ALT_MASK) != 0) {
            modifiers |= InputEvent.ALT_DOWN_MASK;
        }
        if ((modifiers & InputEvent.META_MASK) != 0) {
            modifiers |= InputEvent.META_DOWN_MASK;
        }
        if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
            modifiers |= InputEvent.SHIFT_DOWN_MASK;
        }
        if ((modifiers & InputEvent.CTRL_MASK) != 0) {
            modifiers |= InputEvent.CTRL_DOWN_MASK;
        }
        if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
            modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
        }
    }

    /**
     * Sets old modifiers by the new ones.
     * <p>
     *  通过新的修饰符设置旧的修饰符。
     * 
     */
    private void setOldModifiers() {
        if (id == MOUSE_PRESSED
            || id == MOUSE_RELEASED
            || id == MOUSE_CLICKED)
        {
            switch(button) {
            case BUTTON1:
                modifiers |= BUTTON1_MASK;
                break;
            case BUTTON2:
                modifiers |= BUTTON2_MASK;
                break;
            case BUTTON3:
                modifiers |= BUTTON3_MASK;
                break;
            }
        } else {
            if ((modifiers & BUTTON1_DOWN_MASK) != 0) {
                modifiers |= BUTTON1_MASK;
            }
            if ((modifiers & BUTTON2_DOWN_MASK) != 0) {
                modifiers |= BUTTON2_MASK;
            }
            if ((modifiers & BUTTON3_DOWN_MASK) != 0) {
                modifiers |= BUTTON3_MASK;
            }
        }
        if ((modifiers & ALT_DOWN_MASK) != 0) {
            modifiers |= ALT_MASK;
        }
        if ((modifiers & META_DOWN_MASK) != 0) {
            modifiers |= META_MASK;
        }
        if ((modifiers & SHIFT_DOWN_MASK) != 0) {
            modifiers |= SHIFT_MASK;
        }
        if ((modifiers & CTRL_DOWN_MASK) != 0) {
            modifiers |= CTRL_MASK;
        }
        if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0) {
            modifiers |= ALT_GRAPH_MASK;
        }
    }

    /**
     * Sets new modifiers by the old ones.
     * <p>
     *  使用旧的修饰符设置新的修饰符。
     * 
     * @serial
     */
    private void readObject(ObjectInputStream s)
      throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        if (getModifiers() != 0 && getModifiersEx() == 0) {
            setNewModifiers();
        }
    }
}
